//Top module for exercise 3

#include <systemc.h>
#include "if.h"
#include "processor.h"

class Top : public sc_module
{
	public:
		// Array of pointers to processors. 
		// The last processor is used to connect unused ports.
		// TODO: Better way to solve unconnected port problem while still keeping
		// simple connection loop?
		Processor * iProcessors[NR_OF_PROCESSORS]; 
		
		// Constructor
		Top(sc_module_name name) : sc_module(name)
		{
			// Instantiate processors here.
			char buf[20];
			for(int i = 0; i<NR_OF_PROCESSORS; i++) //row
			{
				sprintf(buf, "Processor%d\0", i);
				iProcessors[i] = new Processor(buf);	
			}
			// Connect processors, processors are connected in an nxn row major matrix.
			// Connecting to processor10 defines an unused port.

			Terminator * iTerminator;
			iTerminator = new Terminator("Terminator");
			for(int i = 0; i<SIZE; i++) //row
			{
				int k = SIZE*i;
				for(int j = 0; j<SIZE;j++) //column
				{
					if (i == 0) // Processor is at top
						iProcessors[k+j]->upp(*iTerminator);
					else
						iProcessors[k+j]->upp(*(iProcessors[k+j-SIZE]));
					if(i == SIZE-1) // Processor is at bottom
						iProcessors[k+j]->downp(*iTerminator);
					else
						iProcessors[k+j]->downp(*(iProcessors[k+j+SIZE]));
					if(j == 0) // Processor is at left edge
						iProcessors[k+j]->leftp(*iTerminator);
					else
						iProcessors[k+j]->leftp(*(iProcessors[k+j-1]));
					if(j == SIZE-1) // Processor is at right edge
						iProcessors[k+j]->rightp(*iTerminator);
					else
						iProcessors[k+j]->rightp(*(iProcessors[k+j+1]));	
				}				
			} 
		srand(time(NULL));
		SC_HAS_PROCESS (Top);
		SC_THREAD(main);
		}
		void main()
		{
			std::vector<int> numbers_found;
			// Prints out array of all the current processor values.
			// Each processor uses one delta cycle to compute values
			for(int j = 0; j<NR_OF_PROCESSORS;j++)
			{
				wait(SC_ZERO_TIME);
			}
			for(int i = 0; i<NR_OF_PROCESSORS; i++)
			{
				if(i % SIZE == 0)
					cout << endl;
				cout << " " << iProcessors[i]->check() << " ";
				numbers_found.push_back(iProcessors[i]->check());
			}
			cout << endl;
			sort (numbers_found.begin(), numbers_found.end());
			for (std::vector<int>::iterator it =numbers_found.begin(); it!=numbers_found.end(); ++it)
				cout << " " << *it;
			cout << endl;
			
			sc_stop;
		}
};


int sc_main (int argc , char *argv[])  
{
  // instantiate top
	Top * iTop;
	iTop = new Top("Top");
  // tracing of signals ...

  // sc_start ...
  sc_start ();
  return 0;
}
